#pragma once
#include "..\Common\Global.h"
#include <winnt.h>
#include <wtypes.h>

class Lexer_Ch;
class Lexer_Str;
class Lexer_Result;
class Lexer_Combinator_Node;

typedef Combinator<LPTSTR,Lexer_Result> Lexer_Combinator;

class Lexer_Ch : public Lexer_Combinator
{
public:
	Lexer_Ch(WCHAR _value,BOOL _Not = FALSE);

	virtual Lexer_Result Parser(LPTSTR& input);

	inline WCHAR Value();
protected:
	WCHAR value;
	BOOL Not;
};

class Lexer_Str : public Lexer_Combinator
{
public:
	Lexer_Str(LPTSTR _value,BOOL _Not = FALSE);

	virtual Lexer_Result Parser(LPTSTR& input);
protected:
	LPTSTR value;
	BOOL Not;
};

class Lexer_Result : public CombinatorResult<LPTSTR,Lexer_Result>
{
public:
	Lexer_Result();
	Lexer_Result(Combinator_MemoryManager<LPTSTR,Lexer_Result>* _MM) : length(0),CombinatorResult<LPTSTR,Lexer_Result>(_MM){}
	Lexer_Result(LPTSTR _value,Combinator_MemoryManager<LPTSTR,Lexer_Result>* _MM) : CombinatorResult<LPTSTR,Lexer_Result>(_value,_MM)
	{
		if(_value) length = wcslen(_value);
		else length = 0;
	}

	//virtual Lexer_Result& operator+(LPTSTR _value);

	virtual Lexer_Result& operator+(Lexer_Result& _value);

	inline int& Length()
	{
		return length;
	}
protected:
	int length;
};

class Lexer_Combinator_Node : public Combinator_Node<LPTSTR,Lexer_Result>
{
public:
	Lexer_Combinator_Node();
	Lexer_Combinator_Node(Combinator<LPTSTR,Lexer_Result>* _value) : Combinator_Node<LPTSTR,Lexer_Result>(_value){}
	Lexer_Combinator_Node(Lexer_Combinator_Node& _value) : Combinator_Node<LPTSTR,Lexer_Result>(_value){}

	Lexer_Combinator_Node& operator+(Lexer_Combinator_Node& _value)
	{
		return (Lexer_Combinator_Node&)__super::operator+(_value);
	}

	Lexer_Combinator_Node& operator|(Lexer_Combinator_Node& _value)
	{
		return (Lexer_Combinator_Node&)__super::operator|(_value);
	}

	Lexer_Combinator_Node& operator&(Lexer_Combinator_Node& _value)
	{
		return (Lexer_Combinator_Node&)__super::operator&(_value);
	}

	Lexer_Combinator_Node& operator-(Lexer_Combinator_Node& _value);

	Lexer_Combinator_Node& operator*()
	{
		return (Lexer_Combinator_Node&)__super::operator*();
	}

	Lexer_Combinator_Node& operator+()
	{
		return (Lexer_Combinator_Node&)__super::operator+();
	}

	static Lexer_Combinator_Node& opt(Lexer_Combinator_Node& _value)
	{
		return (Lexer_Combinator_Node&)Combinator_Node<LPTSTR,Lexer_Result>::opt(_value);
	}
};
